package cc.comac.saic.hkhy.jsrj.gj.inttools.gitlab;

import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CodingErrorAction;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Set;

import org.gitlab4j.api.models.CommitAction;
import org.gitlab4j.models.Constants;
import org.springframework.http.MediaType;

import jakarta.servlet.http.Part;

/**
 * @author huxinshuang
 * @date 2025/7/28
 */
public final class GitlabFileUtils {
    private GitlabFileUtils() {
    }

    private static final Set<String> KNOWN_BINARY_TYPES = Set.of(
        MediaType.APPLICATION_PDF_VALUE,
        "application/msword",
        "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
        "application/vnd.ms-excel",
        "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
        "application/zip",
        MediaType.IMAGE_PNG_VALUE,
        MediaType.IMAGE_GIF_VALUE,
        MediaType.IMAGE_JPEG_VALUE
    );

    private static final Set<Charset> CHARSETS = Set.of(
        StandardCharsets.UTF_8,
        Charset.forName("GB18030"),
        Charset.forName("GB2312"),
        Charset.forName("Big5"),
        StandardCharsets.ISO_8859_1,
        Charset.forName("windows-1252"),
        Charset.forName("Shift_JIS"),
        Charset.forName("EUC-KR")
    );

    public static CommitAction newCommitAction(Part part) throws IOException {
        byte[] bytes;
        try (InputStream inputStream = part.getInputStream()) {
            bytes = inputStream.readAllBytes();
        }
        CommitAction commitAction = new CommitAction();
        commitAction.setFilePath(part.getSubmittedFileName());
        String contentType = part.getContentType();
        if (contentType != null && KNOWN_BINARY_TYPES.contains(contentType.toLowerCase())) {
            commitAction.setContent(Base64.getEncoder().encodeToString(bytes));
            commitAction.setEncoding(Constants.Encoding.BASE64);
        } else {
            for (Charset charset : CHARSETS) {
                try {
                    charset.newDecoder()
                        .onMalformedInput(CodingErrorAction.REPORT)
                        .decode(ByteBuffer.wrap(bytes));
                    commitAction.setContent(new String(bytes, charset));
                    return commitAction;
                } catch (CharacterCodingException ignored) {
                }
            }
            commitAction.setContent(Base64.getEncoder().encodeToString(bytes));
            commitAction.setEncoding(Constants.Encoding.BASE64);
        }
        return commitAction;
    }

}
